home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / language / embedded / mcu / b5_boot.arc / EPB5.C next >
Text File  |  1989-03-22  |  27KB  |  882 lines

  1.         /**************************************************
  2.          *      EPB5 - MC68HC705B5 Serial loader          *
  3.          *                                                *
  4.          *      Compiled using Microsoft C 5.0 Compiler   *
  5.          *      as follows:                               *
  6.          *                   qcl epb5.c /F                *
  7.          *                   link epb5 /ST:0x4fff         *
  8.          *                                                *
  9.          *      Original code by O. Pilloud               *
  10.          *      Rewritten by H. Tireford - March 1989     *
  11.          *                                                *
  12.          **************************************************
  13.          */
  14.  
  15. # define        IGNORE_CKSUM    /* comment out if checksum errors are to be flagged */
  16.  
  17. # include <c:\c\bios.h>
  18. # include <c:\c\stdio.h>
  19. # include <c:\c\stdlib.h>
  20. # include <c:\c\string.h>
  21. # include <c:\c\ctype.h>
  22. # include <c:\c\conio.h>
  23. # include <c:\c\setjmp.h>
  24.  
  25.  
  26.         /*      MCU dependencies
  27.          */
  28. # define        ARRAYSZ         8192            /* B5 memory size (max) */
  29. # define        MAXREC          (ARRAYSZ+100)   /* max size of echo buffer */
  30. # define        FUSE_ADDR       0x1efe
  31. # define        SECE            0x80
  32. # define        BEG_ADDR        0x100
  33. # define        END_ADDR        0x200
  34. # define        TOP_ADDR        8192
  35. # define        BOT_ADDR        256
  36.  
  37. # define        REVISION        "B.0"
  38. # define        BFSIZE          128     /* max record length */
  39. # define        COM1            0       /* serial port number */
  40. # define        FALSE           0
  41. # define        TRUE            !FALSE
  42. # define        uchar           unsigned char
  43.  
  44. # define        FILE_END        0
  45. # define        REC_OK          1       /* valid S0 or S1 record                 */
  46. # define        E_COUNT         -1      /* invalid character count               */
  47. # define        E_BCOUNT        -2      /* invalid byte count                    */
  48. # define        E_ADDR          -3      /* invalid address field                 */
  49. # define        E_CHAR          -4      /* char in S-rec data field is not hex   */
  50. # define        E_CKSUM         -5      /* invalid checksum                      */
  51. # define        E_SEG           -6      /* too many segments                     */
  52. # define        BFSIZE          128     /* length of buffer to hold S records    */
  53.  
  54. # define        MAX_SEG         50      /* maximum number of segments in file    */
  55.  
  56. unsigned int
  57.         line,                   /* input file record number        */
  58.         addr,
  59.         beg_add,
  60.         end_add,
  61.         echo_cnt,
  62.         loaded,
  63.         dumped,
  64.         seg_num;
  65.  
  66. uchar
  67.         buf [BFSIZE],           /* input buffer                    */
  68.         pgm [80],               /* downloadable file name */
  69.         array [ARRAYSZ],        /* S19 file array */
  70.         * echo_ptr,
  71.         echo [MAXREC],
  72.         rx [4],                 /* 4-byte received data */
  73.         word [4],               /* 4-byte transmit data */
  74.         comstat,                /* bios serial function result */
  75.         last_recv,              /* last byte received from MCU */
  76.         sync;                   /* communication sync flag */
  77.  
  78. uchar   dummy_rec [4] = {0x00, 0x00, 0x00, 0x00};   /* record of zeroes */
  79. uchar   exec_rec [4]  = {0x20, 0xfe, 0x00, 0x00};   /* BRA *   */
  80.  
  81. int     NEG = 0x8237;            /* negative address to trigger RAM exec */
  82. int     XADR = 0x0094;
  83. int     PROG = 0x0250;
  84.  
  85.  
  86. jmp_buf mark;
  87.  
  88.  
  89. struct segment {
  90.         unsigned
  91.                 addr,
  92.                 count;
  93.         } segment [MAX_SEG];
  94.  
  95. struct rec {
  96.         unsigned int    addr;   /* load address                           */
  97.         char            * ptr;  /* pointer to next hex pair in data field */
  98.         unsigned char
  99.                         type,   /* record type (ascii 0 or 1)             */
  100.                         bcount; /* number of data bytes (or hex pair)     */
  101.                                 /* pointed to by "ptr"                    */
  102.         } rec;
  103.  
  104.  
  105. char * serial_error[] = {
  106.         "Data ready",
  107.         "Overrun",
  108.         "Parity",
  109.         "Framing",
  110.         "Break",
  111.         "Tx Hold empty",
  112.         "Tx shift empty",
  113.         "Timeout",
  114.         };
  115.  
  116. char * load_error [] = {
  117.         "invalid character count",      /* E_COUNT */
  118.         "invalid byte count",           /* B_COUNT */
  119.         "invalid address field",        /* E_ADDR  */
  120.         "non hexadecimal character",    /* E_CHAR  */
  121.         "invalid checksum",             /* E_CKSUM */
  122.         "too many segments",            /* E_SEG   */
  123.         };
  124.  
  125.         /*      Convert lower-case to upper-case
  126.          */
  127. char
  128. upper (char c)
  129. {
  130.         if (c >= 'a' && c <= 'z')
  131.                 c = c - 'a' + 'A';
  132.         return (char) c;
  133. }
  134.  
  135.  
  136.         /*      Return binary value of an hex character PLUS 1,
  137.          *      or return 0 if not an hex char.
  138.          */
  139. unsigned
  140. ishex (char c)
  141. {
  142.         c = upper (c);
  143.         if (isdigit (c))
  144.                 return c - '0' + 1;
  145.         if (c < 'A' || c > 'F')
  146.                 return 0;
  147.         return c - 'A' + 11;
  148. }
  149.  
  150.  
  151.         /*      Initialize PC serial port
  152.          */
  153. void
  154. init_ser (int port)
  155. {
  156.         comstat = (uchar) _bios_serialcom(_COM_INIT,
  157.                                            port,
  158.                                           _COM_CHR8 |
  159.                                           _COM_NOPARITY |
  160.                                           _COM_9600 );
  161. }
  162.  
  163.  
  164.         /*      Output character to serial port
  165.          */
  166. void
  167. send_char (uchar c, int port)
  168. {
  169.         comstat = (uchar) _bios_serialcom (_COM_SEND, port, c);
  170. }
  171.  
  172.  
  173.         /*      Buffer character echoed by MCU
  174.          */
  175. void
  176. save_echo (uchar c)
  177. {
  178.         if (echo_cnt ++ < MAXREC)
  179.                 * echo_ptr ++ = c;
  180.         else
  181.                 printf ("echo buffer overflow\n");
  182. }
  183.  
  184.  
  185.         /*      Dump echo buffer to console
  186.          */
  187. void
  188. dump_echo (void)
  189. {
  190.         uchar * p, * q, c;
  191.         int   i, j, cnt;
  192.  
  193.         p = & echo[7];
  194.  
  195.         if (echo_cnt < 7) {
  196.                 printf ("echo buffer is empty\n");
  197.                 return;
  198.                 }
  199.  
  200.         printf ("\n*** Bytes received from MC68HC705B5 MCU ***\n");
  201.  
  202.         for (i=0; p < echo_ptr; i++) {
  203.  
  204.                 if ( (i % 16) == 0) {
  205.                         q = p;
  206.                         cnt = 0;
  207.                         printf ("\n%.4x  ", i);
  208.                         }
  209.  
  210.                 /*      for each byte, display its value in ascii hex
  211.                  */
  212.  
  213.                 printf ("%.2x ", (unsigned int) * p ++);
  214.                 cnt ++;
  215.  
  216.                 /*      display ascii printable equivalent
  217.                  *      characters at end of line (group of 16 bytes).
  218.                  */
  219.  
  220.                 if ((i & 15) == 15) {
  221.                         printf ("   ");
  222.                         for (j=0; j < cnt; j++) {
  223.                                 c = * q++;
  224.                                 if (! (c >= ' ' && c <= '~'))
  225.                                         c = '.';
  226.                                 printf ("%c", c);
  227.                                 }
  228.  
  229.                         if (user_abort())       /* check for abort */
  230.                                 break;
  231.                         }
  232.                 }
  233.         printf ("\n");
  234. }
  235.  
  236.  
  237.         /*      Compare bytes we sent with bytes echoed by MCU
  238.          */
  239. void
  240. verify (void)
  241. {
  242.         uchar * p, c;
  243.         int   i, j, k, flag, err, u_abort;
  244.  
  245.         if (! dumped) {
  246.             printf ("Nothing downloaded yet\n");
  247.             return;
  248.             }
  249.  
  250.         err = flag = u_abort = 0;
  251.         p = & echo[7];
  252.         k = echo_cnt - 7;
  253.  
  254.         /*      the bytes we sent to MCU were fetched from array
  255.          *      using the definitions of file segments which was
  256.          *      constructed at the time the file was loaded in PC.
  257.          */
  258.  
  259.         for (i = 1; i < seg_num && ! u_abort; i++) {
  260.  
  261.                 addr = segment [i] . addr;
  262.                 j = segment [i] . count;
  263.  
  264.                 if (k < j) {
  265.                         printf ("Host sent %d bytes (segment %.4x).\n", j, addr);
  266.                         printf ("MCU did not echo %s.\n", k > 0 ? "all of them" : "any");
  267.                         err ++;
  268.                         }
  269.  
  270.                 while (j --)  {
  271.                         if ( (c = array [addr]) != * p ) {
  272.                                 err ++;
  273.                                 if ((flag % 16) == 0) {
  274.                                         if (user_abort()) {
  275.                                             u_abort ++;
  276.                                             break;
  277.                                             }
  278.                                         printf ("\nAddr Sent Recv\n");
  279.                                         }
  280.                                 printf ("%.4x: %.2x   %.2x    %c",
  281.                                         addr, c, * p, (flag++ & 3) == 3 ? '\n' : ' ');
  282.                                 }
  283.                         addr ++;
  284.                         p ++;
  285.                         k --;
  286.                         }
  287.  
  288.                 if (k < 0)
  289.                         break;
  290.                 }
  291.  
  292.         printf ("\nVerify %s\n", err ? "failed" : "succeeded");
  293. }
  294.  
  295.  
  296. void
  297. reset_mcu (int mark)
  298. {
  299.         printf ("Reset MCU %c\n", mark == TRUE ? '!' : ' ');
  300. }
  301.  
  302.  
  303. int
  304. user_abort (void)
  305. {
  306.         unsigned c;
  307.  
  308.         if (_bios_keybrd (_KEYBRD_READY) ) {
  309.                 c = _bios_keybrd (_KEYBRD_READ) & 255;
  310.                 c = upper ((uchar) c);
  311.                 if (c=='X' || c=='Q' || c == 0x3)
  312.                         return 1;
  313.                 }
  314.         return 0;
  315. }
  316.  
  317.  
  318.         /*      Wait until 4 consecutive valid bytes are received
  319.          *      from MCU (as a result of MCU reset).
  320.          */
  321.  
  322. void
  323. synchronize (void)
  324. {
  325.         unsigned c, d, cnt, err;
  326.  
  327.         reset_mcu (FALSE);
  328.  
  329.         for (err = sync = cnt = 0; cnt < 1; ) {
  330.  
  331.                 if (user_abort())
  332.                         longjmp (mark, -1);
  333.  
  334.                 c = _bios_serialcom (_COM_RECEIVE, COM1, 0);
  335.                 d = (c >> 8) & 255;
  336.                 last_recv = (uchar) c & 255;
  337.                 if (! d) {
  338.                         err = 0;
  339.                         cnt ++;
  340.                       }
  341.                 else {
  342.                         cnt = 0;
  343.                         if ( ++ err % 8 == 0)
  344.                                 reset_mcu (TRUE);
  345.                    }
  346.                 }
  347.         sync ++;
  348. }
  349.  
  350.  
  351.         /*      Get character from serial port; wait
  352.          *      until one is received, if necessary.
  353.          */
  354. uchar
  355. rec_char (int port)
  356. {
  357.         unsigned c, i, j, d, cnt;
  358.  
  359.         /*      Allow for a maximum of 16 errors prior to aborting
  360.          */
  361.  
  362.         for (cnt = 0; cnt < 16; cnt ++) {
  363.  
  364.                 if (user_abort())
  365.                      break;
  366.  
  367.                 c = _bios_serialcom (_COM_RECEIVE, port, 0);
  368.                 d = (c >> 8) & 255;
  369.  
  370.                 if (! d) {              /* valid character. return it */
  371.                         cnt = 0;
  372.                         c &= 255;
  373.                         save_echo (last_recv = (uchar) c);
  374.                         return (uchar) (c);
  375.                     }
  376.  
  377.                 /*      Display relevant error message.
  378.                  */
  379.  
  380.                 for (i=1, j=0; j < 8; i <<= 1, j++)
  381.                         if (i & d)
  382.                                 printf (" -%s- ", serial_error[j]);
  383.  
  384.                 printf ("(%.4x)\n", c);
  385.                 }
  386.  
  387.         /*      Abort, i.e., re-enter command interpreter due to
  388.          *      too many communication errors or operator's abort.
  389.          */
  390.  
  391.         printf ("\n%s !!!\n",
  392.            cnt == 16 ? "serial link problem" : "aborted");
  393.  
  394.         longjmp (mark, -1);
  395. }
  396.  
  397.  
  398.         /*      Send 6 bytes to MCU (target address + 4 data bytes)
  399.          *      while simultaneously accepting 4 bytes from it.
  400.          */
  401. void
  402. protocol (uchar word[], uchar rx[], int address)
  403. {
  404.         int     i;
  405.         uchar   * wp, * rp;
  406.  
  407.         wp = & word[0];
  408.         rp = & rx[0];
  409.  
  410.         /*      Receive one byte from MCU before sending data unless
  411.          *      at the very beginning of the transfer.
  412.          */
  413.  
  414.         if (sync != 1)
  415.                 * rp++ = rec_char (COM1);   /* receive first (lo) echo */
  416.         else {
  417.                 * rp ++ = last_recv;
  418.                 sync ++;
  419.         }
  420.  
  421.         send_char ((uchar) (address >> 8), COM1);  /* send address hi */
  422.  
  423.         * rp++ = rec_char (COM1);           /* receive second echo */
  424.         send_char ((uchar) (address & 0xff), COM1); /* send address lo */
  425.  
  426.         * rp++ = rec_char (COM1);           /* receive third echo */
  427.         send_char (* wp++, COM1);           /* send first (lo) data byte */
  428.  
  429.         * rp = rec_char (COM1);             /* receive fourth echo */
  430.         send_char (* wp++, COM1);           /* send second data byte */
  431.  
  432.         send_char (* wp++, COM1);           /* send third data byte */
  433.  
  434.         send_char (* wp, COM1);             /* send fourth data byte */
  435. }
  436.  
  437.         /*      Download array, 4 bytes at a time, accounting for
  438.          *      the file segments constructed by "loadfile".
  439.          */
  440. void
  441. main_proc (void)
  442. {
  443.         int     i, j, k;
  444.  
  445.         unsigned int
  446.                 addr;
  447.  
  448.         for (i = 1; i < seg_num; i++) {
  449.  
  450.                 addr = segment [i] . addr;
  451.                 j = segment [i] . count;
  452.  
  453.                 do {
  454.                         for (k=0; k < 4; k++)
  455.                                 word [k] = array [addr + k];
  456.                         protocol (word, rx, addr);
  457.                         addr += 4;
  458.                         j -= 4;
  459.  
  460.                 } while (j > 0);
  461.  
  462.             }
  463. }
  464.  
  465.         /*      send 3 records to empty the pipeline, blow the fuse
  466.          *      if required and be ready for the next device
  467.          */
  468. void
  469. reset_pipe (void)
  470. {
  471.         protocol (exec_rec, rx, XADR);
  472.         protocol (dummy_rec,rx, PROG);
  473.         protocol (dummy_rec,rx, NEG );
  474. }
  475.  
  476.  
  477.         /*      Display menu of commands and return user's selection
  478.          */
  479. int
  480. prompt (void)
  481. {
  482.         int c;
  483.  
  484.         printf ("\n\n\t* S    \tShow MCU memory contents");
  485.         printf ("\n\t* F    \tLoad S19 file from disk");
  486.         printf ("\n\t* D    \tDownload last loaded file to MCU");
  487.         printf ("\n\t* E    \tExamine \'echo\' buffer");
  488.         printf ("\n\t* V    \tVerify \'echo\' buffer against downloaded file");
  489.         printf ("\n\t* X    \tExit\n");
  490.  
  491.         while (TRUE) {
  492.  
  493.                 printf ("\n\t  Your choice ? ");
  494.  
  495.                 c = getche();
  496.                 c = upper ((uchar) c);
  497.  
  498.                 if (c == 'X')
  499.                         c = 'Q';
  500.  
  501.                 if (c == 'S' || c == 'D' || c == 'Q' || c == 'F' || c == 'E' || c == 'V') {
  502.                         putchar ('\n');
  503.                         break;
  504.                         }
  505.                 }
  506.  
  507.         return c;
  508. }
  509.  
  510.         /*      Initialize MCU memory image in PC
  511.          */
  512. void
  513. clear_array (void)
  514. {
  515.         int     i;
  516.         uchar   * p;
  517.  
  518.         for (i = 0, p = array; i < ARRAYSZ; i++)
  519.                 * p ++ = 0;
  520. }
  521.  
  522.  
  523.         /*      Get beginning and ending addresses for MCU memory display
  524.          */
  525. void
  526. get_limits (void)
  527. {
  528.         char    inp [40];
  529.         unsigned int
  530.                 beg, end;
  531.  
  532.         while (TRUE) {
  533.  
  534.                 printf ("Beg addr %.4x ", beg_add);
  535.                 gets (inp);
  536.                 if (inp[0])
  537.                         sscanf (inp, "%x", & beg);
  538.                 else
  539.                         beg = beg_add;
  540.                 printf ("End addr %.4x ", end_add);
  541.                 gets (inp);
  542.                 if (inp[0])
  543.                         sscanf (inp, "%x", & end);
  544.                 else
  545.                         end = end_add;
  546.  
  547.                 if (beg > end)
  548.                         continue;
  549.  
  550.                 if (beg % 4)
  551.                         beg &= ~3;
  552.                 if (end % 4) {
  553.                         end &= ~3;
  554.                         end += 4;
  555.                         }
  556.                 if ( (beg <= end) && end <= TOP_ADDR && beg >= BOT_ADDR) {
  557.                         beg_add = beg;
  558.                         end_add = end;
  559.                         break;
  560.                         }
  561.           }
  562. }
  563.  
  564.  
  565.         /*      Read "n" hex char pointed to indirectly by "s" and store the converted
  566.          *      value into location pointed to by "v". Update character pointer.
  567.          *      Return 0 if valid hex string, non-zero otherwise.
  568.          */
  569. int
  570. gethex (char * * s, unsigned * v, unsigned n)
  571. {
  572.         char            * p;
  573.         unsigned        i, x;
  574.  
  575.         i = 0;
  576.         p = * s;
  577.         while (n --) {
  578.                 if (! (x = ishex (* p++)) )
  579.                         break;
  580.                 i <<= 4;
  581.                 i |= (x - 1);
  582.                 }
  583.         * v = i;
  584.         * s = p;
  585.  
  586.         return x == 0;
  587. }
  588.  
  589.  
  590.         /*      Get next S0 or S1 record from input file.
  591.          *      return 0 if EOF, <0 if invalid record, >0 otherwise.
  592.          */
  593. int
  594. get_S_record (FILE * fp)
  595. {
  596.         char    c, * s, * p;
  597.         unsigned char   ck;
  598.         unsigned  val, len;
  599.  
  600.         while (fgets (buf, BFSIZE-1, fp) != (char *) NULL ) {
  601.  
  602.                 line ++;
  603.                 for (s = buf; * s; s++)
  604.                         * s = upper (* s);
  605.  
  606.                 if (* -- s != '\n')             /* line length exceeds buf capacity */
  607.                         continue;               /* discard                          */
  608.                 len = s - buf;                  /* record length, incl. S-rec type  */
  609.                 s = buf;
  610.  
  611.                 if (* s ++ != 'S')              /* not an S record. ignore.         */
  612.                         continue;
  613.  
  614.                 c = * s++;
  615.  
  616.                 switch (c) {
  617.  
  618.                 case '9':
  619.                         break;
  620.  
  621.                 case '0':
  622.                 case '1':
  623.  
  624.                         rec . type = c;
  625.                         if ( len < 4 || gethex (&s, &val, 2))
  626.                                 return E_COUNT;
  627.                         ck = val;               /* start building checksum */
  628.                         if ( len != (((rec . bcount = val) <<1) + 4) )
  629.                                 return E_BCOUNT;
  630.  
  631.                         if ( len < 8 || gethex (&s, &val, 4))
  632.                                 return E_ADDR;
  633.  
  634.                         ck += val & 255;
  635.                         ck += (val >> 8) & 255;
  636.                         rec . addr  = val;
  637.                         rec . bcount -= 3;      /* number of data bytes (cksum excl.)   */
  638.                         rec . ptr = s;          /* pointer to first data byte in record */
  639.                         len = rec . bcount;
  640.  
  641.                                         /* continue to compute checksum on data bytes and
  642.                                          * check that it matches the one at end of record
  643.                                          */
  644.                         while (len --) {
  645.                                 if (gethex (&s, &val, 2))
  646.                                         return E_CHAR;
  647.                                 ck += val & 255;
  648.                                 }
  649.                         ck = ~ck;               /* one's complement */
  650.                         gethex (&s, &val, 2);
  651.  
  652.                         if (ck != val & 255) {
  653.  
  654. # ifdef IGNORE_CKSUM
  655.                                 printf ("%s*** %s (error ignored) at line %d\n",
  656.                                         buf, load_error [-E_CKSUM - 1], line);
  657.                                 return REC_OK;
  658. # endif
  659.  
  660.                                 return E_CKSUM;
  661.  
  662.                                 }
  663.  
  664.                                         /* record passed all tests. exit
  665.                                          * and tell the world it is valid.
  666.                                          */
  667.                         return REC_OK;
  668.  
  669.                 default:                /* ignore records other than S0 or S1 */
  670.                         break;
  671.                         }
  672.  
  673.                 continue;
  674.                 }
  675.  
  676.         return FILE_END;                /* EOF */
  677. }
  678.  
  679.  
  680.  
  681.         /*      Load file given as argument; if it does not exist, try
  682.          *      to load same file with extension ".S19", if any.
  683.          */
  684. void
  685. loadfile (char * s)
  686. {
  687.         FILE    * infil;
  688.         int     i, j, x;
  689.         unsigned int
  690.                 val, k;
  691.         char    * p;
  692.  
  693.         loaded = 0;
  694.         strcpy (pgm, s);
  695.  
  696.         while (TRUE) {
  697.  
  698.                 if ( (infil = fopen (pgm, "r")) != (FILE *) NULL)
  699.                         break;
  700.  
  701.                 strcat (pgm, ".s19");
  702.                 if ( (infil = fopen (pgm, "r")) == (FILE *) NULL) {
  703.                         printf ("Cannot open file %s\n", s);
  704.                         return;
  705.                         }
  706.                 break;
  707.                 }
  708.  
  709.         printf ("Loading file %s ...\n", pgm);
  710.  
  711.         clear_array ();
  712.  
  713.         line = seg_num = 0;
  714.         segment [0] . addr = 0xffff;
  715.         segment [0] . count = 0;
  716.  
  717.         /*      Construct file segments while loading
  718.          */
  719.  
  720.         while ( (i = get_S_record (infil)) > 0 ) {
  721.  
  722.                 j = rec . bcount;
  723.                 p = rec . ptr;
  724.  
  725.                 if ( rec . type == '0') {       /* S0 record handling */
  726.  
  727.                         if (! j)
  728.                                 printf ("(no header)\n");
  729.                         else {
  730.                                 printf ("header: ");
  731.                                 while (j --) {
  732.                                         gethex (&p, &val, 2);
  733.                                         putchar ( (uchar) val & 255 );
  734.                                         }
  735.                                 putchar ('\n');
  736.                           }
  737.                         continue;
  738.                         }
  739.                                                 /* S1 record handling */
  740.  
  741.                 if ( rec . addr == (segment [seg_num] . addr + segment [seg_num] . count) )
  742.                         segment [seg_num] . count += rec . bcount;
  743.                 else {
  744.                         if (seg_num ++ >= MAX_SEG) {
  745.                                 i = E_SEG;
  746.                                 break;
  747.                                 }
  748.                         printf ("getting segment %.4x\n", rec . addr);
  749.                         segment [seg_num] . addr  = rec . addr;
  750.                         segment [seg_num] . count = rec . bcount;
  751.                   }
  752.  
  753.                 while (j --) {
  754.                         gethex (&p, &val, 2);
  755.                         array [rec . addr ++] = (uchar) val & 255;
  756.                         }
  757.                 }
  758.  
  759.         seg_num ++;
  760.  
  761.         fclose (infil);
  762.  
  763.         /*      adjust segments so that their beg address
  764.          *      be a multiple of 4.
  765.          */
  766.  
  767.         for (j=1; j < seg_num; j++) {
  768.                 k = segment [j] . addr;
  769.                 x = k % 4;
  770.                 if (x) {
  771.                        segment [j] . addr &= ~3;
  772.                        segment [j] . count += x;
  773.                        }
  774.                 }
  775.  
  776.         if (i < 0)
  777.                 printf ("%s\n%s at line %d\n", buf, load_error [-i - 1], line);
  778.         else {
  779.                 loaded ++;
  780.                 dumped = 0;
  781.                 i = seg_num -1;
  782.                 printf ("%d segment%sloaded\n", i, i == 1 ? " " : "s ");
  783.                 printf ("\nSecurity fuse blowing is%senabled\n",
  784.                       array [FUSE_ADDR] & SECE ? " " : " not ");
  785.         }
  786. }
  787.  
  788.  
  789.         /*      Program entry point
  790.          */
  791. void
  792. main (int argc, char *argv[])
  793. {
  794.         char    name [80];
  795.         int     cmd;
  796.  
  797.         printf ("\nEPB5 Serial Loader, rev %s\n", REVISION) ;
  798.  
  799.         /*      Set default values
  800.          */
  801.  
  802.         loaded = 0;
  803.         beg_add = BEG_ADDR;
  804.         end_add = END_ADDR;
  805.  
  806.         /*      Load file if one is specified in command line
  807.          */
  808.  
  809.         if (argc == 2)
  810.              loadfile (argv [1]);
  811.  
  812.         init_ser (COM1);                        /* init serial port */
  813.  
  814.         printf ("\nInsert MC68HC705B5 in loader socket.\n");
  815.  
  816.         /*
  817.          *      Command interpreter
  818.          */
  819.  
  820.         while ( (cmd = prompt()) != 'Q') {
  821.  
  822.                 switch (cmd) {
  823.  
  824.                 case 'F':                       /* load file from disk */
  825.                         printf ("Enter file name: ");
  826.                         gets (name);
  827.                         loadfile (name);
  828.                         break;
  829.  
  830.                 case 'E':                       /* Examine echo buffer */
  831.                         dump_echo ();
  832.                         break;
  833.  
  834.                 case 'V':                       /* Verify echo buffer against downloaded file */
  835.                         if (! loaded)
  836.                                 printf ("No file currently loaded ! (use F command)\n");
  837.                         else
  838.                                 verify ();
  839.                         break;
  840.  
  841.                 case 'S':                       /* Show MCU memory contents */
  842.                         get_limits ();
  843.  
  844.                 case 'D':                       /* Download */
  845.  
  846.                         if (cmd == 'D') {
  847.                                 if (! loaded) {
  848.                                    printf ("No file currently loaded ! (use F command)\n");
  849.                                    break;
  850.                                    }
  851.                                 else
  852.                                    printf ("Ready to download %s\n", pgm);
  853.                                 }
  854.  
  855.                         echo_cnt = 0;
  856.                         echo_ptr = & echo[0];
  857.  
  858.                         if (! setjmp (mark)) {
  859.                               synchronize ();
  860.  
  861.                               if (cmd == 'D') {
  862.                                         main_proc ();
  863.                                         reset_pipe ();
  864.                                         dumped ++;
  865.                                         verify ();
  866.                                         }
  867.                               else {
  868.                                         for (addr=beg_add; (addr <= end_add); addr += 4)
  869.                                                 protocol (dummy_rec, rx, addr);
  870.  
  871.                                         reset_pipe ();
  872.                                         dump_echo ();
  873.                                   }
  874.                               }
  875.  
  876.                         break;
  877.  
  878.                 default:
  879.                         break;
  880.                 }
  881.         }
  882. }